import { v4 as uuidv4 } from "uuid";
import { responseJson } from "~/server/utils/helper";
import jwt from "jsonwebtoken";

export const secret = "shhhhh";
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  const { refreshToken, accessToken } = body;
  if (!accessToken) {
    const token = await useStorage("redis").getItem(accessToken);
    if (token) {
      return responseJson(0, "成功", {
        accessToken: accessToken,
        refreshToken: refreshToken,
      });
    }
  }
  // 参数校验
  if (!refreshToken) {
    return responseJson(400, "失败", "请提供 refreshToken");
  }

  // 验证 refreshToken 有效性（需结合 Redis）
  const storedToken = await useStorage("redis").getItem(refreshToken);
  if (!storedToken) {
    return responseJson(401, "失败", "无效的 refreshToken");
  }
  try {
    // 验证 accessToken 并生成新 token
    const decoded = await verifyToken(refreshToken); // 封装为 Promise
    const userId = decoded.data.uid;
    const newToken = generateToken(
      userId,
      Math.floor(Date.now() / 1000) + 60 * 60
    ); // 生成新 accessToken
    const newRefreshToken = generateToken(
      userId,
      Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7
    ); // 生成新 accessToken

    await useStorage("redis").removeItem(refreshToken); // 使旧 refreshToken 失效
    const uuid = uuidv4();
    await useStorage("redis").setItem(uuid, newToken, {
      ttl: Math.floor(Date.now() / 1000) + 60 * 60,
    });
    await useStorage("redis").setItem(newRefreshToken, newToken, {
      ttl: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7,
    });
    return responseJson(0, "成功", {
      accessToken: uuid,
      refreshToken: newRefreshToken,
    });
  } catch (error) {
    console.error("Token 刷新异常:", error);
    return responseJson(500, "失败", "服务器内部错误");
  }
});

// 封装 JWT 验证为 Promise
const verifyToken = (token: string): Promise<any> => {
  return new Promise((resolve, reject) => {
    jwt.verify(token, secret, (err, decoded) => {
      err ? reject(err) : resolve(decoded);
    });
  });
};

// 生成新 accessToken
const generateToken = (userId: string, exp: number = 3600) => {
  return jwt.sign({ data: { uid: userId }, exp: exp }, secret);
};
